/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "灯光节点.h"

#include "节点/插座/list/list物体插座.h"
#include "节点/插座/list/list数值插座.h"
#include "节点/插座/通用插座.h"
#include "节点/socket_utils.h"
#include "节点/节点树.h"

#include "Context/数据创建销毁.h"
#include "Context/当前默认操作数据.h"




C_平行光节点::C_平行光节点(S_设备环境& ctx) : C_节点基类(DEF_平行光节点, E_节点类型::e_节点Type_灯光) {
	m_Ctx = ctx;
	m_Name = L"平行光";
	m_Ob = f_node_创建虚拟体网格物体(ctx, E_物体类型::t_平行光);
	f_NodeCtx_录物体类节点(this, m_Ob);

	m_灯光标志位 = f_alloc_UI32FlagBitsProp(nullptr, L"灯光遮罩");
	m_灯光标志位.m_私有 = true;
	f_prop_UI32(m_灯光标志位) = 1;


	C_插座基类* socket;
	DEF_创建Vec3插座_I(L"位置", &(m_Ob->m_变换.location));
	DEF_创建Vec3插座_I(L"旋转", &(m_Ob->m_变换.rotation));
	DEF_创建Vec3插座_I(L"缩放", &(m_Ob->m_变换.scale));

	DEF_创建Vec3插座_I(L"颜色", nullptr);
	DEF_创建F32插座_I(L"强度", nullptr);
	DEF_创建F32插座_I(L"散度", nullptr);
	DEF_创建F32插座_I(L"衰减", nullptr);
	//DEF_创建Vec3插座_I(L"颜色", &(light->m_color));
	//DEF_创建F32插座_I(L"强度", &(light->m_intensity));
	//DEF_创建F32插座_I(L"散度", &(light->m_diffusivity));
	//DEF_创建F32插座_I(L"衰减", &(light->m_falloff));

	DEF_创建物体插座_O(L"灯光物体");


	f_get输出插座(1)->f_setData(m_灯光);


	f_scene_渲染器分配平行光内存(f_NodeCtx_get默认场景());
}

C_平行光节点::~C_平行光节点() {
}

bool C_平行光节点::f_update() {
	S_LigthParallel light{};

	vec3 dir = { 0, 1, 0 };
	auto mat = f_ob_get变换矩阵(m_Ob);
	auto rotMat = f_mat44_to_33(mat, true);
	light.m_dir = rotMat * dir;
	light.m_color = { 1,1,1 };
	light.m_diffusivity = 0.1;
	light.m_enable = true;
	light.m_intensity = 1;
	light.m_mask = f_prop_UI32(m_灯光标志位);
	
	f_scene_渲染器设置平行光(f_NodeCtx_get默认场景(), m_Ob->m_ID, light);
	f_render_刷新渲染(f_NodeCtx_get默认场景());
	return false;
}

S_物体* C_平行光节点::f_get虚拟体() {
	return m_Ob;
}

void C_平行光节点::f_入回收() {
	assert(m_Ob);
	//f_NodeCtx_get默认场景()->f_remove物体(m_Ob, E_场景物体容器类型::e_集合);
	f_scene_渲染器设置平行光启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, false);
	m_Ob->m_渲染 = false;
	f_node_移除虚拟体(m_Ob);
}

void C_平行光节点::f_回收() {
	//f_NodeCtx_get默认场景()->f_add物体({ m_Ob }, E_场景物体容器类型::e_集合);
	f_scene_渲染器设置平行光启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, true);
	m_Ob->m_渲染 = true;
	f_node_创建平行光虚拟体(m_Ob);
}

void C_平行光节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_灯光标志位, f);
	f_ob_Load物体(m_Ob, f);
}

void C_平行光节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_灯光标志位, f);
	f_ob_Save物体(m_Ob, f);
}

C_节点基类* f_node_创建平行光节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_平行光节点(ctx);
}

C_节点基类* f_node_加载平行光节点(S_设备环境& ctx, FILE* f) {
	C_平行光节点* node = new C_平行光节点(ctx);
	return node;
}

void f_node_保存平行光节点(C_节点基类* n, FILE* f) {
	C_平行光节点* node = dynamic_cast<C_平行光节点*>(n);
}




C_点光源节点::C_点光源节点(S_设备环境& ctx) : C_节点基类(DEF_点光源节点, E_节点类型::e_节点Type_灯光) {
	m_Ctx = ctx;
	m_Name = L"点光源";
	
	m_Ob = f_node_创建虚拟体网格物体(ctx, E_物体类型::t_点光源);
	f_NodeCtx_录物体类节点(this, m_Ob);
	

	m_灯光标志位 = f_alloc_UI32FlagBitsProp(nullptr, L"灯光遮罩");
	m_灯光标志位.m_私有 = true;
	f_prop_UI32(m_灯光标志位) = 1;



	C_插座基类* socket;
	//DEF_创建物体_1D插座_I(L"光源");

	DEF_创建Vec3插座_I(L"位置", &(m_Ob->m_变换.location));
	DEF_创建F32插座_I(L"亮度", nullptr);
	DEF_创建F32插座_I(L"大小", nullptr);
	DEF_创建Vec3插座_I(L"缩放", &(m_Ob->m_变换.scale));

	DEF_创建物体插座_O(L"灯光物体");


	DEF_F32插座数据(f_get输入插座(3)) = 0.5;
	DEF_Vec3插座数据(f_get输入插座(4)) = {1,1,1};
	
	//S_节点数据::G_点光源ID.f_Gen();
	f_get输出插座(1)->f_setData(m_Ob);

}

C_点光源节点::~C_点光源节点() {
	f_node_移除虚拟体(m_Ob);
}

bool C_点光源节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	//auto* 灯光组 = DEF_物体插座_1D数据(socket1, 0);
	
	S_物体* m_灯光;
	f_get输出插座(1)->f_setData(m_Ob);


	S_LigthPoint light = {};
	light.m_pos = f_ob_get全局坐标(m_Ob, m_Ob->m_实例ID);
	light.m_intensity = DEF_F32插座数据(f_get输入插座(2));
	light.m_falloff = DEF_Vec3插座数据(f_get输入插座(4)).x;
	light.m_mask = f_prop_UI32(m_灯光标志位);
	light.m_enable = true;

	f_scene_渲染器设置点光源(f_NodeCtx_get默认场景(), m_Ob->m_ID, light);
	f_render_刷新渲染(f_NodeCtx_get默认场景());
	return false;
}

S_物体* C_点光源节点::f_get虚拟体() {
	//m_Ob = DEF_物体插座数据(f_get输出插座(1), 0);
	return m_Ob;
}

void C_点光源节点::f_入回收() {
	assert(m_Ob);
	f_scene_渲染器设置点光源启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, false);
	m_Ob->m_渲染 = false;
	f_node_移除虚拟体(m_Ob);
}

void C_点光源节点::f_回收() {
	f_scene_渲染器设置点光源启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, true);
	m_Ob->m_渲染 = true;
	f_node_创建点光源虚拟体(m_Ob);
}

void C_点光源节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_灯光标志位, f);
	f_ob_Load物体(m_Ob, f);
}

void C_点光源节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_灯光标志位, f);
	f_ob_Save物体(m_Ob, f);
}

C_节点基类* f_node_创建点光源节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_点光源节点(ctx);
}

C_节点基类* f_node_加载点光源节点(S_设备环境& ctx, FILE* f) {
	C_点光源节点* node = new C_点光源节点(ctx);
	return node;
}

void f_node_保存点光源节点(C_节点基类* n, FILE* f) {
	C_点光源节点* node = dynamic_cast<C_点光源节点*>(n);
}




C_聚光灯节点::C_聚光灯节点(S_设备环境& ctx) : C_节点基类(DEF_聚光灯节点, E_节点类型::e_节点Type_灯光) {
	m_Ctx = ctx;
	m_Name = L"聚光灯";
	m_Ob = f_node_创建虚拟体网格物体(ctx, E_物体类型::t_聚光灯);
	f_NodeCtx_录物体类节点(this, m_Ob);


	m_灯光标志位 = f_alloc_UI32FlagBitsProp(nullptr, L"灯光遮罩");
	m_灯光标志位.m_私有 = true;
	f_prop_UI32(m_灯光标志位) = 1;


	C_插座基类* socket;
	DEF_创建Vec3插座_I(L"位置", &(m_Ob->m_变换.location));
	DEF_创建Vec3插座_I(L"旋转", &(m_Ob->m_变换.rotation));
	DEF_创建Vec3插座_I(L"缩放", &(m_Ob->m_变换.scale));
	DEF_创建F32插座_I(L"散度", nullptr);

	DEF_创建物体插座_O(L"灯光物体");


	f_get输出插座(1)->f_setData(m_Ob);
}

C_聚光灯节点::~C_聚光灯节点() {
	f_node_移除虚拟体(m_Ob);
}

bool C_聚光灯节点::f_update() {
	DEF_Vec3插座数据(f_get输入插座(2)).y = 0;

	f_node_设置灯光虚拟网格范围(m_Ob, { 0, m_Ob->m_变换.scale.y });
	f_render_刷新渲染(f_NodeCtx_get默认场景());

	//auto mesh = f_ob_fromMesh(m_Ob, 0);
	//m_Ob->m_Bound = f_surface_计算包围盒(mesh, nullptr, m_Ob->m_PickIndirect.firstVertex, m_Ob->m_PickIndirect.vertexCount);
	//light.m_maks = f_prop_UI32(m_灯光标志位);


	return false;
}

S_物体* C_聚光灯节点::f_get虚拟体() {
	//m_Ob = DEF_物体插座数据(f_get输出插座(1), 0);
	return m_Ob;
}

void C_聚光灯节点::f_入回收() {
	assert(m_Ob);
	f_scene_渲染器设置聚光灯启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, false);
	f_node_移除虚拟体(m_Ob);
}

void C_聚光灯节点::f_回收() {
	f_scene_渲染器设置聚光灯启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, true);
	f_node_创建聚光灯虚拟体(m_Ob);
	
}

void C_聚光灯节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_灯光标志位, f);
	f_ob_Load物体(m_Ob, f);
}

void C_聚光灯节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_灯光标志位, f);
	f_ob_Save物体(m_Ob, f);
}

C_节点基类* f_node_创建聚光灯节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_聚光灯节点(ctx);
}

C_节点基类* f_node_加载聚光灯节点(S_设备环境& ctx, FILE* f) {
	C_聚光灯节点* node = new C_聚光灯节点(ctx);
	return node;
}

void f_node_保存聚光灯节点(C_节点基类* n, FILE* f) {
	C_聚光灯节点* node = dynamic_cast<C_聚光灯节点*>(n);
}



C_区域光节点::C_区域光节点(S_设备环境& ctx) : C_节点基类(DEF_区域光节点, E_节点类型::e_节点Type_灯光) {
	m_Ctx = ctx;
	m_Name = L"区域光";

	m_Ob = f_node_创建虚拟体网格物体(ctx, E_物体类型::t_区域光);
	f_NodeCtx_录物体类节点(this, m_Ob);

	
	m_灯光标志位 = f_alloc_UI32FlagBitsProp(nullptr, L"灯光遮罩");
	m_灯光标志位.m_私有 = true;
	f_prop_UI32(m_灯光标志位) = 1;



	C_插座基类* socket;
	DEF_创建Vec3插座_I(L"位置", &(m_Ob->m_变换.location));
	DEF_创建Vec3插座_I(L"旋转", &(m_Ob->m_变换.rotation));
	DEF_创建Vec3插座_I(L"缩放", &(m_Ob->m_变换.scale));

	DEF_创建Vec3插座_I(L"颜色", nullptr);
	DEF_创建F32插座_I(L"强度", nullptr);
	DEF_创建F32插座_I(L"散度", nullptr);
	DEF_创建F32插座_I(L"衰减", nullptr);



	DEF_创建物体插座_O(L"灯光物体");

	DEF_Vec3插座数据(f_get输入插座(4)) = { 1,1,1 };
	DEF_F32插座数据(f_get输入插座(5)) = 1;
	DEF_F32插座数据(f_get输入插座(6)) = 0.3;

	f_get输出插座(1)->f_setData(m_Ob);

	
	m_形状类型 = f_alloc_EnumProp(nullptr, { {L"矩形",""}, {L"圆形"} }, L"形状");
	m_形状类型.m_私有 = true;
	
}

C_区域光节点::~C_区域光节点() {
	f_prop_Release(m_形状类型);
	f_node_移除虚拟体(m_Ob);
}

bool C_区域光节点::f_update() {
	
	switch (f_prop_enum(m_形状类型)) {
	case 0:
		m_Ob->m_Type = E_物体类型::t_区域光_方形;
		f_node_设置灯光虚拟网格类型(m_Ob, E_物体类型::t_区域光_方形);
		break;

	case 1:
		m_Ob->m_Type = E_物体类型::t_区域光_圆形;
		f_node_设置灯光虚拟网格类型(m_Ob, E_物体类型::t_区域光_圆形);
		break;

	default:
		break;
	}

	/*auto* socket1 = f_get输入插座(1);
	auto* 灯光组 = DEF_物体插座_1D数据(socket1, 0);
	f_get输出插座(1)->f_setData(灯光组);

	S_物体* m_灯光;
	if (!socket1->f_isLink() || !灯光组->count) {
		f_core_array_resize((S_Array*)灯光组, 1);
		灯光组->ptr_userData[0] = m_Ob;

		m_灯光 = m_Ob;
	}
	else {
		m_灯光 = 灯光组->ptr_userData[0];
	}*/

	S_LigthArea light;
	light.m_color = DEF_Vec3插座数据(f_get输入插座(4));
	light.m_intensity = DEF_F32插座数据(f_get输入插座(5));
	light.m_diffusivity = DEF_F32插座数据(f_get输入插座(6));
	light.m_mask = f_prop_UI32(m_灯光标志位);
	light.m_enable = true;

	f_scene_渲染器设置区域光(f_NodeCtx_get默认场景(), m_Ob->m_ID, light);
	f_render_刷新渲染(f_NodeCtx_get默认场景());
	
	
	return false;
}

S_物体* C_区域光节点::f_get虚拟体() {
	//m_Ob = DEF_物体插座数据(f_get输出插座(1), 0);
	return m_Ob;
}

void C_区域光节点::f_入回收() {
	assert(m_Ob);
	f_scene_渲染器设置区域光启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, false);
	f_node_移除虚拟体(m_Ob);
}

void C_区域光节点::f_回收() {
	f_scene_渲染器设置区域光启用(f_NodeCtx_get默认场景(), m_Ob->m_ID, true);
	f_node_创建聚光灯虚拟体(m_Ob);
}

void C_区域光节点::f_切换区域光形状() {

}

void C_区域光节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_5, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_形状类型, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_灯光标志位, 下一次读取数据指针);
			下一次读取数据指针 = f_ob_Load物体(m_Ob, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);

	//if (S_引擎::读取加载文件版本号 <= S_节点数据::g_低版本号_5) {
	//	f_prop_Load(m_形状类型, f);
	//	f_prop_Load(m_灯光标志位, f);
	//	f_ob_Load物体(m_Ob, f);
	//}
	//else {
	//	
	//}
}

void C_区域光节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_形状类型, 块);
	f_prop_Save(m_灯光标志位, 块);
	f_ob_Save物体(m_Ob, 块);

	f_file_保存文件块(f, 文件块, 块);
	//if (S_引擎::读取加载文件版本号 <= S_节点数据::g_低版本号_5) {
	//	f_prop_Save(m_形状类型, f);
	//	f_prop_Save(m_灯光标志位, f);
	//	f_ob_Save物体(m_Ob, f);
	//}
	//else {
	//	
	//}
}

C_节点基类* f_node_创建面光源节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_区域光节点(ctx);
}

C_节点基类* f_node_加载面光源节点(S_设备环境& ctx, FILE* f) {
	C_区域光节点* node = new C_区域光节点(ctx);
	return node;
}

void f_node_保存面光源节点(C_节点基类* n, FILE* f) {
	C_区域光节点* node = dynamic_cast<C_区域光节点*>(n);
}



